package com.ruoyi.register;

import com.ruoyi.common.annotation.Anonymous;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;
import java.util.Date;
import java.util.regex.Pattern;

@RestController
@RequestMapping("/api/auth")
@CrossOrigin("*")
@Anonymous
public class UserAuthController {

    // 账号验证正则表达式（3-20位字母或数字）
    private static final Pattern ACCOUNT_PATTERN = Pattern.compile("^[A-Za-z0-9]{3,20}$");

    // 昵称验证正则表达式（2-20位字符，不包含空格）
    private static final Pattern NICKNAME_PATTERN = Pattern.compile("^[^\\s]{2,20}$");

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    /**
     * 注册接口（强制绑定openid，作为唯一标识）
     * 一个openid只能注册一次
     */
    @PostMapping("/register")
    public Map<String, Object> register(@RequestBody RegisterDto registerDto) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 1. 核心参数验证
            if (registerDto.getAccount() == null || registerDto.getAccount().trim().isEmpty()) {
                result.put("success", false);
                result.put("msg", "账号不能为空");
                return result;
            }

            // 验证账号格式（仅字母和数字，3-20位）
            if (!ACCOUNT_PATTERN.matcher(registerDto.getAccount()).matches()) {
                result.put("success", false);
                result.put("msg", "账号必须包含3-20位字母或数字");
                return result;
            }

            if (registerDto.getPassword() == null || registerDto.getPassword().trim().isEmpty()) {
                result.put("success", false);
                result.put("msg", "密码不能为空");
                return result;
            }

            // 验证密码长度
            if (registerDto.getPassword().trim().length() < 6) {
                result.put("success", false);
                result.put("msg", "密码长度不能少于6位");
                return result;
            }

            // 验证昵称
            if (registerDto.getNickname() == null || registerDto.getNickname().trim().isEmpty()) {
                result.put("success", false);
                result.put("msg", "昵称不能为空");
                return result;
            }

            // 验证昵称格式
            if (!NICKNAME_PATTERN.matcher(registerDto.getNickname()).matches()) {
                result.put("success", false);
                result.put("msg", "昵称必须包含2-20位字符，且不支持空格");
                return result;
            }

            // 强制验证openid（作为唯一标识）
            if (registerDto.getOpenid() == null || registerDto.getOpenid().trim().isEmpty()) {
                result.put("success", false);
                result.put("msg", "系统需要微信授权，请完成微信登录");
                return result;
            }

            // 2. 唯一性校验
            // 2.1 账号唯一
            String checkAccountSql = "SELECT COUNT(*) FROM wx_user WHERE account = ?";
            Integer accountCount = jdbcTemplate.queryForObject(
                    checkAccountSql,
                    new Object[]{registerDto.getAccount()},
                    Integer.class
            );
            if (accountCount != null && accountCount > 0) {
                result.put("success", false);
                result.put("msg", "账号已存在");
                return result;
            }

            // 2.2 openid唯一（核心：一个微信账号只能注册一次）
            String checkOpenidSql = "SELECT COUNT(*) FROM wx_user WHERE openid = ?";
            Integer openidCount = jdbcTemplate.queryForObject(
                    checkOpenidSql,
                    new Object[]{registerDto.getOpenid()},
                    Integer.class
            );
            if (openidCount != null && openidCount > 0) {
                result.put("success", false);
                result.put("msg", "该微信账号已注册，请直接登录");
                return result;
            }

            // 3. 保存用户（包含头像地址）
            String encryptPassword = passwordEncoder.encode(registerDto.getPassword());
            String insertSql = "INSERT INTO wx_user " +
                    "(account, nickname, password, openid, avatar_url, role, create_time, update_time) " +
                    "VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
            Date now = new Date();
            int rows = jdbcTemplate.update(
                    insertSql,
                    registerDto.getAccount(),
                    registerDto.getNickname(),
                    encryptPassword,
                    registerDto.getOpenid(),
                    registerDto.getAvatarUrl(),  // 存储头像永久地址URL
                    "玩家",  // 默认角色
                    now,
                    now
            );

            if (rows > 0) {
                result.put("success", true);
                result.put("msg", "注册成功，已绑定微信账号");
                result.put("data", new HashMap<String, Object>() {{
                    put("account", registerDto.getAccount());
                    put("nickname", registerDto.getNickname());
                    put("avatarUrl", registerDto.getAvatarUrl());  // 返回头像地址
                }});
            } else {
                result.put("success", false);
                result.put("msg", "注册失败");
            }
        } catch (Exception e) {
            result.put("success", false);
            result.put("msg", "注册异常: " + e.getMessage());
            e.printStackTrace();
        }

        return result;
    }

    /**
     * 账号密码登录
     */
    @PostMapping("/login")
    public Map<String, Object> login(@RequestBody LoginDto loginDto) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 1. 验证参数
            if (loginDto.getAccount() == null || loginDto.getPassword() == null) {
                result.put("success", false);
                result.put("msg", "账号或密码不能为空");
                return result;
            }

            // 2. 查询用户
            String selectSql = "SELECT * FROM wx_user WHERE account = ?";
            Map<String, Object> userMap;
            try {
                userMap = jdbcTemplate.queryForMap(selectSql, loginDto.getAccount());
            } catch (Exception e) {
                result.put("success", false);
                result.put("msg", "账号或密码错误");
                return result;
            }

            // 3. 验证密码
            String dbPassword = (String) userMap.get("password");
            if (!passwordEncoder.matches(loginDto.getPassword(), dbPassword)) {
                result.put("success", false);
                result.put("msg", "账号或密码错误");
                return result;
            }

            // 4. 登录成功，返回用户信息（包含头像地址）
            result.put("success", true);
            result.put("msg", "登录成功");
            result.put("data", new HashMap<String, Object>() {{
                put("account", userMap.get("account"));
                put("nickname", userMap.get("nickname"));
                put("avatarUrl", userMap.get("avatar_url"));  // 返回头像地址
                put("role", userMap.get("role"));
                put("token", generateToken((Long) userMap.get("id"), (String) userMap.get("account")));
            }});

        } catch (Exception e) {
            result.put("success", false);
            result.put("msg", "登录异常: " + e.getMessage());
            e.printStackTrace();
        }

        return result;
    }

    /**
     * 微信一键登录（通过openid直接登录，无需密码）
     */
    @PostMapping("/login/wechat")
    public Map<String, Object> wechatLogin(@RequestBody OpenidDto openidDto) {
        Map<String, Object> result = new HashMap<>();
        String openid = openidDto.getOpenid();

        if (openid == null || openid.isEmpty()) {
            result.put("success", false);
            result.put("msg", "请先完成微信授权");
            return result;
        }

        try {
            // 通过openid查询用户
            String sql = "SELECT * FROM wx_user WHERE openid = ?";
            Map<String, Object> userMap = jdbcTemplate.queryForMap(sql, openid);

            // 直接登录成功，返回用户信息（包含头像地址）
            result.put("success", true);
            result.put("msg", "微信一键登录成功");
            result.put("data", new HashMap<String, Object>() {{
                put("account", userMap.get("account"));
                put("nickname", userMap.get("nickname"));
                put("avatarUrl", userMap.get("avatar_url"));  // 返回头像地址
                put("role", userMap.get("role"));
                put("token", generateToken((Long) userMap.get("id"), (String) userMap.get("account")));
            }});

        } catch (Exception e) {
            result.put("success", false);
            result.put("msg", "该微信账号未注册，请先注册");
        }
        return result;
    }

    // 生成令牌（实际项目建议用JWT）
    private String generateToken(Long userId, String account) {
        return "token_" + userId + "_" + account + "_" + System.currentTimeMillis();
    }

    // 注册参数DTO
    public static class RegisterDto {
        private String account;      // 账号
        private String nickname;     // 昵称
        private String password;     // 密码
        private String openid;       // 微信唯一标识
        private String avatarUrl;    // 头像永久地址URL

        // getter/setter
        public String getAccount() { return account; }
        public void setAccount(String account) { this.account = account; }
        public String getNickname() { return nickname; }
        public void setNickname(String nickname) { this.nickname = nickname; }
        public String getPassword() { return password; }
        public void setPassword(String password) { this.password = password; }
        public String getOpenid() { return openid; }
        public void setOpenid(String openid) { this.openid = openid; }
        public String getAvatarUrl() { return avatarUrl; }
        public void setAvatarUrl(String avatarUrl) { this.avatarUrl = avatarUrl; }
    }

    // 登录参数DTO
    public static class LoginDto {
        private String account;  // 账号
        private String password; // 密码

        // getter/setter
        public String getAccount() { return account; }
        public void setAccount(String account) { this.account = account; }
        public String getPassword() { return password; }
        public void setPassword(String password) { this.password = password; }
    }

    // 微信登录参数DTO
    public static class OpenidDto {
        private String openid;

        // getter/setter
        public String getOpenid() { return openid; }
        public void setOpenid(String openid) { this.openid = openid; }
    }
}
